package br.com.sgh.beans;

import br.com.sgh.dao.AcervoDAO;
import br.com.sgh.dao.EmprestimoDAO;
import br.com.sgh.dao.FuncionarioDAO;
import br.com.sgh.dao.TituloDAO;
import br.com.sgh.entidade.Acervo;
import br.com.sgh.entidade.Emprestimo;
import br.com.sgh.entidade.Funcionario;
import br.com.sgh.entidade.Titulo;
import br.com.sgh.suport.ComparaObjetos;
import br.com.sgh.suport.TitulosMaisEmprestado;
import br.com.sgh.util.FacesContextUtil;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

@ManagedBean
@ViewScoped
public class DevolucaoBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private StreamedContent arquivoRetorno;
    private Emprestimo emprestimo;
    private List<Emprestimo> emprestimos;
    private Integer codAcervo;
    private Integer codEmprestimo;
    private List<Titulo> titulos;
    private List<Acervo> acervos;
    private List<TitulosMaisEmprestado> titulosMaisEmprestados = new ArrayList<TitulosMaisEmprestado>();

    private EmprestimoDAO emprestimoDao() {
        EmprestimoDAO<Emprestimo> dao = new EmprestimoDAO<Emprestimo>(Emprestimo.class, FacesContextUtil.getRequestSession());
        return dao;
    }

    private FuncionarioDAO funcionarioDao() {
        FuncionarioDAO<Funcionario> dao = new FuncionarioDAO<Funcionario>(Funcionario.class, FacesContextUtil.getRequestSession());
        return dao;
    }

    private TituloDAO tituloDao() {
        TituloDAO<Titulo> dao = new TituloDAO<Titulo>(Titulo.class, FacesContextUtil.getRequestSession());
        return dao;
    }

    private AcervoDAO acervoDao() {
        AcervoDAO<Acervo> dao = new AcervoDAO<Acervo>(Acervo.class, FacesContextUtil.getRequestSession());
        return dao;
    }

    public void devolver(Emprestimo em) {
        emprestimo = em;
        //emprestimo.setDataDevolucao(new Date());
    }

    public String devolucaoCodigoBarras() {
        if ((this.codAcervo == null) || (this.codAcervo < 1)) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Código do acevo incorreto!", null));
            return "/restrito/devolucao.faces";
        } else {
            emprestimos = emprestimoDao().verificaDisponibilidadeAcervo(codAcervo);
            if (emprestimos.size() > 0) {
                emprestimo = emprestimos.get(0);
                emprestimo.setDataDevolucao(new Date());
                emprestimoDao().atualizar(emprestimo);
                this.codAcervo = null;
                emprestimo = new Emprestimo();
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Devolução Realizada com Sucesso!", null));
            } else {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Codigo do acervo não encontrado para devolução!", null));
            }
            return null;
        }
    }

    @PostConstruct
    public void livrosMaisEmprestados() {
        int total;
        titulos = tituloDao().listaTiulosEmprestado();

        for (Titulo t : titulos) {
            acervos = acervoDao().buscarAcervoTitulo(t.getCodTitulo());
            total = 0;
            for (Acervo a : acervos) {
                emprestimos = emprestimoDao().emprestimoPorAcervo(a.getCodAcervo());
                if (emprestimos.size() > 0) {
                    for (Emprestimo e : emprestimos) {
                        total++;
                    }
                }
            }
            if (total > 0) {
                TitulosMaisEmprestado titulosMaisEmprestado = new TitulosMaisEmprestado();
                titulosMaisEmprestado.setTitulo(t.getDescricao());
                titulosMaisEmprestado.setQtde(total);

                //System.out.println("Titulo : " + titulosMaisEmprestado.getTitulo() + " Total Emprestimo : " + titulosMaisEmprestado.getQtde());
                titulosMaisEmprestados.add(titulosMaisEmprestado);
            }
        }
        ComparaObjetos ob = new ComparaObjetos();
        Collections.sort(titulosMaisEmprestados, ob);
    }

    public StreamedContent getArquivoRetorno() throws DocumentException, FileNotFoundException, IOException {
        System.err.println("Entro no metodo");
        Document document = new Document(PageSize.A4);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, baos);
        document.open();

        Font f = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.BOLD);
        Paragraph t1 = new Paragraph("SGBC - BIBLIOTECA CORPORATIVA", f);
        t1.setAlignment(Element.ALIGN_CENTER);
        document.add(t1);

        Paragraph t2 = new Paragraph("SORRISO - MT", f);
        t2.setAlignment(Element.ALIGN_CENTER);
        document.add(t2);

        Paragraph p = new Paragraph("Ranking de Livros Emprestado");
        p.setAlignment(Element.ALIGN_CENTER);
        document.add(p);
        try {

            Font fc = new Font(Font.FontFamily.TIMES_ROMAN, 8);
            Font fh = new Font(Font.FontFamily.TIMES_ROMAN, 8, Font.BOLD);

            if (titulosMaisEmprestados.size() > 0) {

                PdfPTable table = new PdfPTable(new float[]{0.01f, 0.07f, 0.02f});

                table.setSpacingBefore(5.0f);
                table.setWidthPercentage(100.0f);

                table.setHorizontalAlignment(Element.ALIGN_LEFT);

                table.addCell(new Phrase("Ranking", fh));
                table.addCell(new Phrase("Título", fh));
                table.addCell(new Phrase("Qtde", fh));

                int ranking = 1;
                for (TitulosMaisEmprestado e : titulosMaisEmprestados) {
                    table.addCell(new Phrase(String.valueOf(ranking)+"º", fc));
                    table.addCell(new Phrase(e.getTitulo(), fc));
                    table.addCell(new Phrase(String.valueOf(e.getQtde()), fc));
                    ranking++;
                }
                document.add(table);

            }
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro ao tentar Gerar o Relatório", "Erro"));
        }
        //document.add(table);
        document.close();
        FileOutputStream fos = new FileOutputStream("C:\\PDF\\arqPDFexemplo2.pdf");
        InputStream arquivo = new FileInputStream("C:\\PDF\\arqPDFexemplo2.pdf");
        fos.write(baos.toByteArray());
        fos.close();

        arquivoRetorno = new DefaultStreamedContent(arquivo, "application/pdf", "reltorio.pdf");

        return arquivoRetorno;
    }

    public String devolucaoTelaEmprestimo(Emprestimo em) {
        System.out.println("============ Emprestimo codigoo " + codEmprestimo);
        emprestimo = em;
        return "/restrito/devolucao.faces";
    }

    public String confirmarDevolucao() {
        System.out.println(">>>>>>>>>>>> Devolução " + emprestimo.getAcervo().getTitulo().getDescricao() + "  Codigo " + emprestimo.getCodEmprestimo());
        if (emprestimo.getCodEmprestimo() != null || emprestimo.getCodEmprestimo() > 0) {
            emprestimo.setDataDevolucao(new Date());
            emprestimoDao().atualizar(emprestimo);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Devolução Realizada com Sucesso!", null));
            this.codAcervo = null;
            emprestimo = new Emprestimo();
        } else {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Digite o codigo do acevo para solicitar a devolução!", null));
        }
        return "/restrito/devolucao.faces";
    }

    private Funcionario usuarioLogado() {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext external = context.getExternalContext();
        String login = external.getRemoteUser();

        List<Funcionario> lista = funcionarioDao().verificaLogin(login);
        Funcionario f = lista.get(0);
        return f;
    }

    public String cancelar() {
        this.codAcervo = null;
        emprestimo = null;
        return "/restrito/devolucao.faces";
    }

    public Emprestimo getEmprestimo() {
        if (emprestimo == null) {
            emprestimo = new Emprestimo();
        }
        return emprestimo;
    }

    public void setEmprestimo(Emprestimo emprestimo) {
        this.emprestimo = emprestimo;
    }

    public List<Emprestimo> getEmprestimos() {
        return emprestimos = emprestimoDao().listarImprestimoPendentesUsuario(usuarioLogado().getCodFuncionario());
    }

    public void setEmprestimos(List<Emprestimo> emprestimos) {
        this.emprestimos = emprestimos;
    }

    public Integer getCodAcervo() {
        return codAcervo;
    }

    public void setCodAcervo(Integer codAcervo) {
        this.codAcervo = codAcervo;
    }

    public Integer getCodEmprestimo() {
        return codEmprestimo;
    }

    public void setCodEmprestimo(Integer codEmprestimo) {
        this.codEmprestimo = codEmprestimo;
    }

    public List<Titulo> getTitulos() {
        return titulos;
    }

    public void setTitulos(List<Titulo> titulos) {
        this.titulos = titulos;
    }

    public List<Acervo> getAcervos() {
        return acervos;
    }

    public void setAcervos(List<Acervo> acervos) {
        this.acervos = acervos;
    }

    public List<TitulosMaisEmprestado> getTitulosMaisEmprestados() {
        return titulosMaisEmprestados;
    }

    public void setTitulosMaisEmprestados(List<TitulosMaisEmprestado> titulosMaisEmprestados) {
        this.titulosMaisEmprestados = titulosMaisEmprestados;
    }

}
